retrobenchfandomcom-20200216-history
Programming Arduino in Assembly
The Arduino is a microcontroller board based on the ATmega 328p (168 on older models). As such, it is programmable with standard Atmel assembly code. Further, the GCC compiler allows the use of inline assembly with other C-code, making programming the Arduino in assembly straightforward. Example Code The following code turns the LED attached to pin 13 "on": void setup() { asm volatile( "SBI %0, %1 \n\t" //pinMode(13, OUTPUT); :: "I" (_SFR_IO_ADDR(DDRB)), "I" (DDB5) ); } void loop() { asm volatile( "SBI %0, %1 \n\t" //digitalWrite(13, HIGH); :: "I" (_SFR_IO_ADDR(PORTB)), "I" (PORTB5) ); } As with standard Arduino, void setup() is executed once then void loop() is executed repeatedly. First, the function asm volatile starts with a string containing your assembly code. In this case, it is "SBI %0, %1 \n\t". This is a normal line of assembly code that sets the bit in port %0, pin %1.The Arduino has 3 ports B, C, and D which contain pins 8-13, A0-A7, and 0-7, respectively. More information may be found in the "See Also" section. "\n\t" in this case is the end-of-line character that notifies the GCC compiler that the current line of assembly has ended and that the next line has begun (similar to the action of the ";" in C). Next there is a "I" (_SFR_IO_ADDR(PORTB)) . . . In making your own programs, this portion will contain all the ports and pins that your program will use. "I" notifies the compiler to return a "port/pin" datatype for (_SFR_IO_ADDR()) or (PORTB/C/D); your program will then use %0, %1. . . etc. to use the first/second . . .etc port/pin specified at the bottom. For exampe, in the case of the lower asm code, %0 means the address given by the compiler to (_SFR_IO_ADDR(PORTB)) and %1 means the address given by the compiler to (PORTB5). If the program were to have more pins, more %numbers would be used. Addressing Pins Each pin on the Arduino technically has 3 registers: *DDRB/C/D - read/write this register to read/set direction (pinMode INPUT or OUTPUT) *PORT/B/C/D - read/write this register read/set the voltage (digitalWrite HIGH or LOW) *PIN/B/C/D - read only pin. This register's bits are changed externally and read for digital input (digitalRead) It is important to note that pin 0 (RX) should NEVER be set to "OUTPUT" unless absolutely necessary. Unlike C, assembly does not have any safety settings to prevent you setting the RX pin to OUTPUT permanently and thus disabling serial communications. It is important to set it back to INPUT as soon as possible to prevent unwanted behavior. Time Delays There are no built-in time delay instructions on the AVR instruction set other than NOP, which halts the processor for one cycle (62.5 nanoseconds). Thus it is the smallest time delay possible. In order to make a time delay on the length of milliseconds or more, loops must be used. For example, the following code is a subroutine that delays by (approximately) one second. "OneSecondDelay: \n\t" //subroutine declaration "LDI r16, 80 \n\t" "0: CPI r16, 0 \n\t" "BREQ 1f \n\t" // "LDI r17, 200 \n\t" "2: CPI r17, 0 \n\t" "BREQ 3f \n\t" //----------------------------------------------------------------- "LDI r18, 200 \n\t" "4: CPI r18, 0 \n\t" "BREQ 5f \n\t" "SUBI r18, 1 \n\t" "RJMP 4b \n\t" "5: \n\t" //----------------------------------------------------------------- "SUBI r17, 1 \n\t" "RJMP 2b \n\t" "3: \n\t" // "SUBI r16, 1 \n\t" "RJMP 0b \n\t" "1: RET \n\t" //1 second Delay Instead of writing thousands of lines of NOP, this bit of code contains 3 loops nested inside each other to provide an exponential increase in delay time, to conserve space. The two inner loops iterate 200 times each, which gives 40 000 iterations. The outer loop then iterates 80 times, which gives a total number of 3 200 000 iterations. This many iterations, multiplied by 5 operations per iteration, gives 16 000 000 processor cycles With the 16MHz clock speed of the Arduino, it gives an approximate 1-second delay. Notes See Also *Instruction Set Manual. *Pin Mapping of the ATmega328/168. *AVR Playground. *Port Manipulation. *GCC Inline Assembly Tutorial Category:Arduino Category:Programming Category:Code Category:Not Lego Category:Tagisang